home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / Telnet 2.6.1d1 4⁄26⁄94 Folder / source / main / DlogUtils.c < prev    next >
Text File  |  1994-04-18  |  19KB  |  686 lines

  1. /*
  2. *    DlogUtils.c
  3. *    Very Useful Dialog Utilities Apple SHOULD have provided in the toolbox...
  4. *
  5. *****************************************************************
  6. *    NCSA Telnet for the Macintosh                                *
  7. *                                                                *
  8. *    National Center for Supercomputing Applications                *
  9. *    Software Development Group                                    *
  10. *    152 Computing Applications Building                            *
  11. *    605 E. Springfield Ave.                                        *
  12. *    Champaign, IL  61820                                        *
  13. *                                                                *
  14. *    Copyright (c) 1986-1992,                                    *
  15. *    Board of Trustees of the University of Illinois                *
  16. *****************************************************************
  17. *  Revisions:
  18. *  8/92        Telnet 2.6:    Initial version.  Jim Browne
  19. */
  20.  
  21. #ifdef MPW
  22. #pragma segment 7
  23. #endif
  24.  
  25. #include "TelnetHeader.h"
  26. #include "DlogUtils.proto.h"
  27. #include "netevent.proto.h"
  28. #include "newresrc.h"
  29.  
  30. #include "Popup.h"
  31. #include "popup.proto.h"
  32.  
  33. pascal short modalProc(DialogPtr dptr, EventRecord *evt, short *item);
  34. PROTO_UPP(modalProc, ModalFilter);
  35. pascal short FileHook(short item, DialogPtr theDialog);
  36. PROTO_UPP(FileHook, DlgHook);
  37. pascal Boolean    FolderFilter(FileParam *pbp);
  38. PROTO_UPP(FolderFilter, FileFilter);
  39.  
  40. void GetTEText( DialogPtr dptr, short item, Str255 str)
  41. {
  42.     short type;
  43.     Handle itemh;
  44.     Rect theRect;
  45.  
  46.     GetDItem(dptr, item, &type, &itemh, &theRect);
  47.     GetIText(itemh, str);
  48. }
  49.  
  50. void SetTEText( DialogPtr dptr, short item, Str255 str)
  51. {
  52.     short type;
  53.     Handle itemh;
  54.     Rect theRect;
  55.  
  56.     GetDItem(dptr, item, &type, &itemh, &theRect);
  57.     SetIText(itemh, str);
  58. }
  59.  
  60. void Hilite( DialogPtr dptr, short item, short value)
  61. {
  62.     short Type;
  63.     Handle Itemh;
  64.     Rect Box;
  65.  
  66.     GetDItem(dptr, item, &Type, &Itemh, &Box);
  67.     HiliteControl((ControlHandle)Itemh, value);
  68. }
  69.  
  70. void FlipCheckBox( DialogPtr dptr, short item)
  71. {
  72.     short type;
  73.     Handle itemHdl;
  74.     Rect box;
  75.  
  76.     GetDItem(dptr, item, &type, &itemHdl, &box);
  77.     SetCtlValue((ControlHandle)itemHdl, (GetCtlValue((ControlHandle)itemHdl) == 0) ? 1 : 0);
  78. }
  79.  
  80. void FlipRadioButton( DialogPtr dptr, short item)
  81. {
  82.     short type;
  83.     Handle itemHdl;
  84.     Rect box;
  85.  
  86.     GetDItem(dptr, item, &type, &itemHdl, &box);
  87.     SetCtlValue((ControlHandle)itemHdl, (GetCtlValue((ControlHandle)itemHdl) == 0) ? 1 : 0);
  88. }
  89.  
  90. void SetCntrl( DialogPtr dptr, short item, short value)
  91. {
  92.     short Type;
  93.     Handle Itemh;
  94.     Rect Box;
  95.  
  96.     GetDItem(dptr, item, &Type, &Itemh, &Box);
  97.     SetCtlValue((ControlHandle)Itemh, value);
  98. }
  99.  
  100. short GetCntlVal( DialogPtr dptr, short item)
  101. {
  102.     short Type;
  103.     Handle Itemh;
  104.     Rect Box;
  105.  
  106.     GetDItem(dptr, item, &Type, &Itemh, &Box);
  107.     return GetCtlValue((ControlHandle)Itemh);
  108. }
  109.  
  110. #ifndef NO_UNIVERSAL
  111. void UItemAssign( DialogPtr dptr, short item, UserItemUPP proc)
  112. #else
  113. void UItemAssign( DialogPtr dptr, short item, ProcPtr proc)
  114. #endif
  115. /* sets the handler for a user item to the specified procedure. */
  116. {
  117.     Rect ibox;
  118.     char **ihndl;
  119.     short typ;
  120.  
  121.     GetDItem( dptr, item, &typ, &ihndl, &ibox);
  122.     SetDItem( dptr, item,  typ, (Handle) proc, &ibox);
  123. }
  124.  
  125. SIMPLE_UPP(OutlineItem, UserItem);
  126. pascal void OutlineItem( DialogPtr dptr, short itm)
  127. {
  128.     Rect ibox;
  129.     char **ihndl;
  130.     short typ;
  131.     short item=itm;
  132.     
  133.     GetDItem( dptr, item, &typ, &ihndl, &ibox);
  134.     PenSize( 3,3);
  135.     InsetRect( &ibox, -4,-4);
  136.     FrameRoundRect( &ibox, 16,16);
  137. }
  138.  
  139. SIMPLE_UPP(VersionNumber, UserItem);
  140. pascal void VersionNumber( DialogPtr dptr, short itm)
  141. {
  142.     Rect ibox;
  143.     char **ihndl;
  144.     short typ;
  145.     short item=itm;
  146.     VersRecHndl version;
  147.     Str63 versionString;
  148.  
  149.     if (version = (VersRecHndl) GetResource('vers',1))
  150.     {
  151.         BlockMove((*version)->shortVersion+*(*version)->shortVersion+1, versionString, *((*version)->shortVersion+*(*version)->shortVersion+1)+1);
  152.         ReleaseResource((Handle)version);
  153.     }
  154.     else
  155.         *versionString = 0;
  156.  
  157.     GetDItem( dptr, item, &typ, &ihndl, &ibox);
  158.     TextFont( 3);
  159.     TextSize( 9);
  160.     MoveTo( ibox.left+((ibox.right-ibox.left)/2)-(StringWidth(versionString)/2), ibox.bottom-2);
  161.     DrawString(versionString);
  162. }
  163.  
  164. SIMPLE_UPP(modalProc, ModalFilter);
  165. pascal short modalProc( DialogPtr dptr, EventRecord *evt, short *item)
  166. {
  167.     #pragma unused (dptr)
  168.     short keyCode, key;
  169.  
  170.     if (evt->what == keyDown) {
  171.         key = evt->message & charCodeMask;
  172.         keyCode = (evt->message >>8) & 0xff ;
  173.         if ((key == 0x0d) || (key == 0x03)) { // 0x0d == return, 0x03 == enter
  174.             *item = DLOGOk;
  175.             return(-1);                /* BYU LSC - pascal doesn't like "1" as true */
  176.             }
  177.         if (((key == '.') && (evt->modifiers & cmdKey)) ||
  178.             ((key == 0x1b) && (keyCode == 0x35)) ) {    // 0x35 == escKey
  179.             *item = DLOGCancel;
  180.             return(-1);                /* BYU LSC - pascal doesn't like "1" as true */
  181.             }
  182.         }
  183.     Stask();
  184.     return(FALSE);
  185. }
  186.  
  187. void FlashButton (DialogPtr theDialog, short item)
  188. {
  189.     short itemType;
  190.     ControlHandle theItem;
  191.     Rect itemRect;
  192.     long myticks;
  193.     
  194.     if (item > 0) {
  195.         GetDItem(theDialog,item,&itemType,(Handle *)&theItem,&itemRect);
  196.         HiliteControl(theItem,1);
  197.         Delay(8,&myticks);
  198.         HiliteControl(theItem,0);
  199.     }
  200. }
  201.  
  202. SIMPLE_UPP(DLOGwOK, ModalFilter);
  203. pascal short DLOGwOK( DialogPtr dptr, EventRecord *evt, short *item)
  204. {
  205.     return(MyDLOGfilter(dptr, evt, item, true, false, false));
  206. }
  207.  
  208. SIMPLE_UPP(DLOGwOK_Cancel, ModalFilter);
  209. pascal short DLOGwOK_Cancel( DialogPtr dptr, EventRecord *evt, short *item)
  210. {
  211.     return(MyDLOGfilter(dptr, evt, item, true, true, false));
  212. }
  213.  
  214. SIMPLE_UPP(DLOGwOK_Cancel_Popup, ModalFilter);
  215. pascal short DLOGwOK_Cancel_Popup( DialogPtr dptr, EventRecord *evt, short *item)
  216. {
  217.     return(MyDLOGfilter(dptr, evt, item, true, true, true));
  218. }
  219.  
  220. //    Our standard modal dialog box filter.
  221. SIMPLE_UPP(MyDLOGfilter, ModalFilter);
  222. pascal short MyDLOGfilter( DialogPtr dptr, EventRecord *evt, short *item, 
  223.                             Boolean hasOK, Boolean hasCancel, Boolean hasPopup)
  224. {
  225.     short keyCode, key, iType;
  226.     Handle iHndl;
  227.     Rect iRect;
  228.  
  229.     SetPort(dptr);
  230.     if (evt->what == keyDown) {
  231.         key = evt->message & charCodeMask;
  232.         keyCode = (evt->message >>8) & 0xff ;
  233.         if (((key == 0x0d) || (key == 0x03)) && hasOK) { // 0x0d == return, 0x03 == enter
  234.             *item = DLOGOk;                // ok
  235.             FlashButton(dptr, DLOGOk);
  236.             return(-1);
  237.             }
  238.         if ((((key == '.') && (evt->modifiers & cmdKey)) ||
  239.             ((key == 0x1b) && (keyCode == 0x35))) && hasCancel) {    // 0x35 == escKey
  240.             *item = DLOGCancel;
  241.             FlashButton(dptr, DLOGCancel);
  242.             return(-1);
  243.             }
  244.         }
  245.     else if ((evt->what == updateEvt) && hasOK) {
  246.         if ((WindowPtr)evt->message == dptr) {
  247.             GetDItem(dptr,DLOGOk,&iType,&iHndl,&iRect);    // ok
  248.             PenSize(3,3);
  249.             InsetRect(&iRect,-4,-4);
  250.             FrameRoundRect(&iRect,16,16);
  251.             }
  252.     }
  253.     
  254.     if ((evt->what == mouseDown) && hasPopup)
  255.         return(PopupMousedown(dptr, evt, item));
  256.  
  257.     Stask();
  258.     return(FALSE);
  259. }
  260.  
  261. #if 0
  262. //    Our standard modal dialog box filter with code to handle popup user items.
  263. pascal short MyDLOGfilterWPopupFilter( DialogPtr dptr, EventRecord *evt, short *item)
  264. {
  265.     short keyCode, key, iType;
  266.     Handle iHndl;
  267.     Rect iRect;
  268.  
  269.     SetPort(dptr);
  270.     if (evt->what == keyDown) {
  271.         key = evt->message & charCodeMask;
  272.         keyCode = (evt->message >>8) & 0xff ;
  273.         if ((key == 0x0d) || (key == 0x03)) { // 0x0d == return, 0x03 == enter
  274.             *item = DLOGOk;                // ok
  275.             FlashButton(dptr, DLOGOk);
  276.             return(-1);
  277.             }
  278.         if (((key == '.') && (evt->modifiers & cmdKey)) ||
  279.             ((key == 0x1b) && (keyCode == 0x35)) ) {    // 0x35 == escKey
  280.             *item = DLOGCancel;
  281.             FlashButton(dptr, DLOGCancel);
  282.             return(-1);
  283.             }
  284.         }
  285.     else if (evt->what == updateEvt) {
  286.         if ((WindowPtr)evt->message == dptr) {
  287.             GetDItem(dptr,DLOGOk,&iType,&iHndl,&iRect);    // ok
  288.             PenSize(3,3);
  289.             InsetRect(&iRect,-4,-4);
  290.             FrameRoundRect(&iRect,16,16);
  291.             }
  292.     }
  293.     
  294.     if (evt->what == mouseDown) return(PopupMousedown(dptr, evt, item));
  295.     Stask();
  296.     return(FALSE);
  297. }
  298. #endif
  299.  
  300. #ifdef    NO_UNIVERSAL
  301. #define LMSetSFSaveDisk(SFSaveDiskValue) ((* (short *) 0x0214) = (SFSaveDiskValue))
  302. #define LMGetSFSaveDisk() (* (short *) 0x0214)
  303. #define LMGetCurDirStore() (* (long *) 0x0398)
  304. #define LMSetCurDirStore(CurDirStoreValue) ((* (long *) 0x0398) = (CurDirStoreValue))
  305. #endif
  306.  
  307. void    SelectDirectory(short *VRefNum, long *DirID)
  308. {
  309.     Point        where;
  310.     SFReply        sfr;
  311.     
  312.     LMSetSFSaveDisk( - (*VRefNum));
  313.     LMSetCurDirStore(*DirID);
  314.     
  315.     StandardFileCenter(&where, WDSET_DLOG);
  316.     
  317.     TelInfo->setdir = 0;                    /* clear dir found flag */
  318.     
  319.     SFPGetFile( where, NULL, FolderFilterUPP, -1, NULL,    /* BYU LSC */
  320.         FileHookUPP, &sfr, WDSET_DLOG,
  321.         modalProcUPP); 
  322.  
  323.     if (TelInfo->setdir)    {                /* we got a dir */
  324.         *VRefNum = - LMGetSFSaveDisk();
  325.         *DirID = LMGetCurDirStore();
  326.         }
  327. //    else {
  328. //        if(!sfr.good) return;    /* real cancel button got hit */
  329. //        GetWDInfo(sfr.vRefNum, VRefNum, DirID, &junk);
  330. //    }
  331.     
  332. }
  333.  
  334. SIMPLE_UPP(FileHook, DlgHook);
  335. pascal short    FileHook( short item, DialogPtr theDialog)
  336. {
  337. #pragma unused(theDialog)
  338.     if(item == 11) {                    /* Set Directory Button */
  339.             TelInfo->setdir = 1;
  340.             
  341.             return(3);        /* pretend we hit cancel, but we didn't */
  342.         }
  343.     else if (item == 12)
  344.         item = 9;            /* these don't count, map to disabled item */
  345.  
  346.     return(item);
  347. }
  348.  
  349. SIMPLE_UPP(FolderFilter, FileFilter);
  350. pascal Boolean    FolderFilter(FileParam *pbp)
  351. {
  352.     if (pbp->ioFlAttrib & 0x0010) return(FALSE);
  353.     else return(-1);
  354. }
  355.  
  356. OSErr SetIndString(StringPtr theStr,short resID,short strIndex)
  357. {
  358.    Handle theRes;               /* handle pointing to STR# resource */
  359.    short numStrings;            /* number of strings in STR# */
  360.    short ourString;             /* counter to index up to strIndex */
  361.    char *resStr;                /* string pointer to STR# string to replace */
  362.    long oldSize;                /* size of STR# resource before call */
  363.    long newSize;                /* size of STR# resource after call */
  364.    unsigned long offset;        /* resource offset to str to replace*/
  365.  
  366.    /* make sure index is in bounds */
  367.  
  368.    if (resID < 1)
  369.    return -1;
  370.  
  371.    /* make sure resource exists */
  372.  
  373.    theRes = GetResource('STR#',resID);
  374.    if (ResError()!=noErr)
  375.    return ResError();
  376.    if (!theRes || !(*theRes))
  377.    return resNotFound;
  378.  
  379.    HLock(theRes);
  380.    HNoPurge(theRes);
  381.  
  382.    /* get # of strings in STR# */
  383.  
  384.    BlockMove(*theRes,&numStrings,sizeof(short));
  385.    if (strIndex > numStrings)
  386.    return resNotFound;
  387.  
  388.    /* get a pointer to the string to replace */
  389.  
  390.    offset = sizeof(short);
  391.    resStr = (char *) *theRes + sizeof(short);
  392.    for (ourString=1; ourString<strIndex; ourString++) {
  393.    offset += 1+resStr[0];
  394.    resStr += 1+resStr[0];
  395.    }
  396.  
  397.    /* grow/shrink resource handle to make room for new string */
  398.  
  399.    oldSize = GetHandleSize(theRes);
  400.    newSize = oldSize - resStr[0] + theStr[0];
  401.    HUnlock(theRes);
  402.    SetHandleSize(theRes,newSize);
  403.    if (MemError()!=noErr) {
  404.    ReleaseResource(theRes);
  405.    return -1;
  406.    }
  407.    HLock(theRes);
  408.    resStr = *theRes + offset;
  409.  
  410.    /* move old data forward/backward to make room */
  411.  
  412.    BlockMove(resStr+resStr[0]+1, resStr+theStr[0]+1, oldSize-offset-resStr[0]-1);
  413.  
  414.    /* move new data in */
  415.  
  416.    BlockMove(theStr,resStr,theStr[0]+1);
  417.  
  418.    /* write resource out */
  419.  
  420.    ChangedResource(theRes);
  421.    WriteResource(theRes);
  422.    HPurge(theRes);
  423.    ReleaseResource(theRes);
  424.  
  425.    return ResError();
  426. }
  427.  
  428. /* A very special thanks to Steve Dorner (sdorner@qualcomm.com) for the following code! */
  429.  
  430. /************************************************************************
  431.  * GetNewMyDialog - get a new dialog, with a bit extra
  432.  ************************************************************************/
  433. WindowPtr GetNewMyDialog(short template,Ptr wStorage,WindowPtr behind,
  434.     void (*centerFunction)(short))
  435. {
  436.     WindowPtr win;
  437.     
  438.     if (wStorage == nil)
  439.     {
  440.         if ((wStorage=NewPtr(sizeof(DialogRecord)))==nil)
  441.             return (nil);
  442.     }
  443.     WriteZero(wStorage, sizeof(WindowRecord));
  444.     
  445.     (*centerFunction)(template);
  446.     win = GetNewDialog(template, wStorage, behind);
  447.     if (win==nil) return(nil);
  448.     SetPort(win);
  449. /*    win->contR = ((GrafPtr)win)->portRect; */
  450. /*    win->qWindow.refCon = CREATOR; */
  451.     return(win);
  452. }
  453.  
  454. /* Do a GetNewMyDialog, but make the text small... */
  455. WindowPtr GetNewMySmallDialog(short template,Ptr wStorage,WindowPtr behind,
  456.     void (*centerFunction)(short))
  457. {
  458.     short size;
  459.     DialogPtr dlogptr;
  460.     
  461.     size = 9;
  462.     SetDAFont(applFont);
  463.     dlogptr = GetNewMyDialog(template,wStorage,behind,centerFunction);
  464.     SetDAFont(systemFont);
  465.     if (dlogptr==nil)
  466.         return 0;
  467.     SetPort(dlogptr);
  468.     TextSize(size);
  469.     TextFont(applFont);
  470.     {
  471.         TEHandle teh = ((DialogPeek)dlogptr)->textH;
  472.         ControlHandle cntl = ((WindowPeek)dlogptr)->controlList;
  473.         (*teh)->txSize = size;
  474.         (*teh)->lineHeight = GetLeading(applFont,size);
  475.         (*teh)->fontAscent = GetAscent(applFont,size);
  476.     }            
  477.  
  478.     /*     For those dialogs with non-system font buttons, make them inititally invisible
  479.         and then do a ShowWindow.  This keeps the Control Manager from every using Chicago
  480.         on our turf. -- JMB */
  481.         
  482.     if (! ((((DialogPeek) dlogptr)->window).visible)) ShowWindow(dlogptr);
  483.     
  484.     return(dlogptr);
  485. }
  486.  
  487. /* Do a GetNewMySmallDialog, but read the item titles from a STR#... */
  488. WindowPtr GetNewMySmallStrangeDialog(short template,Ptr wStorage,WindowPtr behind,
  489.     void (*centerFunction)(short))
  490. {
  491.     short         size, index, limit, itemType;
  492.     DialogPtr     dlogptr;
  493.     Handle        resource;
  494.     ControlHandle    itemHandle;
  495.     Rect        scratchRect;
  496.     Str255        scratchPstring;
  497.     
  498.     size = 9;
  499.     SetDAFont(applFont);
  500.     dlogptr = GetNewMyDialog(template,wStorage,behind,centerFunction);
  501.     SetDAFont(systemFont);
  502.     if (dlogptr==nil)
  503.         return 0;
  504.     SetPort(dlogptr);
  505.     TextSize(size);
  506.     TextFont(applFont);
  507.     {
  508.         TEHandle teh = ((DialogPeek)dlogptr)->textH;
  509.         ControlHandle cntl = ((WindowPeek)dlogptr)->controlList;
  510.         (*teh)->txSize = size;
  511.         (*teh)->lineHeight = GetLeading(applFont,size);
  512.         (*teh)->fontAscent = GetAscent(applFont,size);
  513.     }            
  514.  
  515.     /*     For those dialogs with non-system font buttons, make them inititally invisible
  516.         and then do a ShowWindow.  This keeps the Control Manager from ever using Chicago
  517.         on our turf. -- JMB */
  518.     
  519.     if ((resource = GetResource('STR#', template)) != NULL) {
  520.         limit = *(short *)(*resource);
  521.         ReleaseResource(resource);
  522.         
  523.         for(index = 1; index <= limit; index++) {
  524.             GetDItem(dlogptr, index, &itemType, (Handle *)&itemHandle, &scratchRect);
  525.             if ((itemType == 7) && ((**itemHandle).contrlRfCon == 1991)) {
  526.                 GetIndString(scratchPstring, template, index);
  527.                 SetCTitle(itemHandle, scratchPstring);
  528.                 }
  529.             }
  530.         }
  531.                 
  532.     return(dlogptr);
  533. }
  534.  
  535. /**********************************************************************
  536.  * write zeroes over an area of memory
  537.  **********************************************************************/
  538. void WriteZero(Ptr pointer,long size)
  539. {
  540.     while (size--) *pointer++ = 0;
  541. }
  542.  
  543. /**********************************************************************
  544.  * figure out the appropriate leading for a font
  545.  **********************************************************************/
  546. short GetLeading(short fontID,short fontSize)
  547. {
  548.     FMInput fInInfo;
  549.     FMOutput *fOutInfo;
  550.     
  551.     /* set up the font input struct */
  552.     fInInfo.family = fontID;
  553.     fInInfo.size = fontSize;
  554.     fInInfo.face = 0;
  555.     fInInfo.needBits = FALSE;
  556.     fInInfo.device = 0;
  557.     fInInfo.numer.h = fInInfo.numer.v = 1;
  558.     fInInfo.denom.h = fInInfo.denom.v = 1;
  559.     
  560.     /* get the actual info */
  561.     fOutInfo = FMSwapFont(&fInInfo);
  562.     
  563.     return(((fOutInfo->leading + fOutInfo->ascent + fOutInfo->descent)*fOutInfo->numer.v)/fOutInfo->denom.v);
  564. }
  565.  
  566. /**********************************************************************
  567.  * find ascent font
  568.  **********************************************************************/
  569. short GetAscent(short fontID,short fontSize)
  570. {
  571.     FMInput fInInfo;
  572.     FMOutput *fOutInfo;
  573.     
  574.     /*    set up the font input struct */
  575.     fInInfo.family = fontID;
  576.     fInInfo.size = fontSize;
  577.     fInInfo.face = 0;
  578.     fInInfo.needBits = FALSE;
  579.     fInInfo.device = 0;
  580.     fInInfo.numer.h = fInInfo.numer.v = 1;
  581.     fInInfo.denom.h = fInInfo.denom.v = 1;
  582.     
  583.     /*    get the actual info */
  584.     fOutInfo = FMSwapFont(&fInInfo);
  585.     
  586.     return((fOutInfo->ascent * fOutInfo->numer.v)/fOutInfo->denom.v);
  587. }
  588.  
  589. /************************************************************************
  590.  * CenterRectIn - center one rect in another
  591.  ************************************************************************/
  592. void CenterRectIn(Rect *inner,Rect *outer)
  593. {
  594.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  595.                                      (outer->top+outer->bottom-inner->top-inner->bottom)/2);                                                                    
  596. }
  597.  
  598. /************************************************************************
  599.  * TopCenterRectIn - center one rect in (the bottom of) another
  600.  ************************************************************************/
  601. void TopCenterRectIn(Rect *inner,Rect *outer)
  602. {
  603.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  604.                                      outer->top-inner->top);                                                                    
  605. }
  606.  
  607. /************************************************************************
  608.  * BottomCenterRectIn - center one rect in (the bottom of) another
  609.  ************************************************************************/
  610. void BottomCenterRectIn(Rect *inner,Rect *outer)
  611. {
  612.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  613.                                      outer->bottom-inner->bottom);                                                                    
  614. }
  615.  
  616. /************************************************************************
  617.  * ThirdCenterRectIn - center one rect in (the top 1/3 of) another
  618.  ************************************************************************/
  619. void ThirdCenterRectIn(Rect *inner,Rect *outer)
  620. {
  621.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  622.                                      outer->top-inner->top +
  623.                                      (outer->bottom-outer->top-inner->bottom+inner->top)/3);                                                                    
  624. }
  625.  
  626. void ThirdCenterDialog(short template)
  627. {
  628.   DialogTHndl dTempl;
  629.   Rect r = qd.screenBits.bounds;
  630.   r.top += GetMBarHeight();       
  631.   if ((dTempl=(DialogTHndl)GetResource('ALRT',template)) ||
  632.       (dTempl=(DialogTHndl)GetResource('DLOG',template)))
  633.     ThirdCenterRectIn(&(*dTempl)->boundsRect,&r);
  634. }
  635.  
  636. /************************************************************************
  637.  * StandardFileCenter - figure out where a stdfile dialog should go
  638.  ************************************************************************/
  639. void StandardFileCenter(Point *where, short id)
  640. {
  641.     Rect r,in;
  642.     DialogTHndl dTempl;             
  643.     if ((dTempl=(DialogTHndl)GetResource('ALRT',id)) ||
  644.             (dTempl=(DialogTHndl)GetResource('DLOG',id)))
  645.     {
  646.         r = (*dTempl)->boundsRect;
  647.         in = qd.screenBits.bounds;
  648.         in.top += GetMBarHeight();
  649.         ThirdCenterRectIn(&r,&in);
  650.         where->h = r.left;
  651.         where->v = r.top;
  652.     }
  653.     else
  654.     {
  655.         where->h = 100;
  656.         where->v = 100;
  657.     }
  658. }
  659.  
  660. /* Pascal string utilities */
  661.  
  662. /*    pstrcat - add string 'src' to end of string 'dst' */
  663. void pstrcat(StringPtr dst, StringPtr src)
  664. {
  665.     /* copy string in */
  666.     BlockMove(src + 1, dst + *dst + 1, *src);
  667.     /* adjust length byte */
  668.     *dst += *src;
  669. }
  670.  
  671. /*    pstrinsert - insert string 'src' at beginning of string 'dst' */
  672. void pstrinsert(StringPtr dst, StringPtr src)
  673. {
  674.     /* make room for new string */
  675.     BlockMove(dst + 1, dst + *src + 1, *dst);
  676.     /* copy new string in */
  677.     BlockMove(src + 1, dst + 1, *src);
  678.     /* adjust length byte */
  679.     *dst += *src;
  680. }
  681.  
  682. void pstrcpy(StringPtr dst, StringPtr src)
  683. {
  684.     BlockMove(src, dst, *src + 1);
  685. }
  686.